package com.elong.android.specialhouse.utils;

import android.app.Activity;
import android.content.Context;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.TextView;

import com.elong.android.specialhouse.R;
import com.elong.android.specialhouse.ui.PreferenceTextView;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserFactory;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;

public class PreferencesHelper {
    public final static int DATATYPE_UNKNOWN = -1;
    public final static int DATATYPE_BOOLEAN = 0;
    public final static int DATATYPE_INTEGER = 1;
    public final static int DATATYPE_STRING = 2;
    public final static int DATATYPE_FLOAT = 3;
    public final static int DATATYPE_LIST = 4;

    public final static String ITEMFIELD_KEY = "key";
    public final static String ITEMFIELD_VIEW = "view";
    public final static String ITEMFIELD_TYPE = "type";
    public final static String ITEMFIELD_DEFAULT = "default";
    public final static String ITEMFIELD_ARRAY = "array";
    // private ArrayList<Activity> m_activities = new ArrayList<Activity>();
    private HashMap<Activity, ArrayList<HashMap<String, Object>>> m_registeredActivities = new HashMap<Activity, ArrayList<HashMap<String, Object>>>();
    private HashMap<String, ArrayList<HashMap<String, Object>>> m_inflatedData;
    private HashMap<String, Object> m_defaultValues;
    private SharedPreferences m_preferences;
    private Context m_context;

    public PreferencesHelper(Context context) {
        m_context = context;
        m_preferences = getPreferences();
    }

    public final static String TAG_PREFERENCES = "preferences";
    public final static String TAG_GROUP = "group";
    public final static String TAG_ITEM = "item";
    public final static String ATTR_NAME = "name";
    public final static String ATTR_KEY = "key";
    public final static String ATTR_VIEW = "view";
    public final static String ATTR_TYPE = "type";
    public final static String ATTR_DEFAULTVALUE = "defaultValue";
    public final static String ATTR_ARRAY = "array";

    public void inflate(InputStream input) {
        try {
            XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
            XmlPullParser parser = factory.newPullParser();
            parser.setInput(input, "utf-8");
            int eventType = parser.next();

            ArrayList<HashMap<String, Object>> curList = null;
            String groupKey = null;
            String tag = null;
            while (eventType != XmlPullParser.END_DOCUMENT) {
                switch (eventType) {
                    case XmlPullParser.START_TAG:
                        tag = parser.getName();
                        if (TAG_PREFERENCES.equals(tag)) {
                            m_inflatedData = new HashMap<String, ArrayList<HashMap<String, Object>>>();
                        } else if (TAG_GROUP.equals(tag)) {
                            curList = new ArrayList<HashMap<String, Object>>();
                            groupKey = parser.getAttributeValue(null, ATTR_NAME);
                        } else if (TAG_ITEM.equals(tag)) {
                            HashMap<String, Object> item = new HashMap<String, Object>();
                            // key.
                            item.put(ITEMFIELD_KEY, parser.getAttributeValue(null, ATTR_KEY));

                            // type.

                            int type = DATATYPE_UNKNOWN;
                            String typeStr = parser.getAttributeValue(null, ATTR_TYPE);
                            if (typeStr.equals("boolean")) {
                                type = DATATYPE_BOOLEAN;
                            } else if (typeStr.equals("int")) {
                                type = DATATYPE_INTEGER;
                            } else if (typeStr.equals("string")) {
                                type = DATATYPE_STRING;
                            } else if (typeStr.equals("float")) {
                                type = DATATYPE_FLOAT;
                            } else if (typeStr.equals("list")) {
                                type = DATATYPE_LIST;
                            }
                            item.put(ITEMFIELD_TYPE, type);

                            // view.
                            Class c = R.id.class;
                            item.put(ITEMFIELD_VIEW, c.getField(parser.getAttributeValue(null, ATTR_VIEW)).getInt(null));

                            if (type == DATATYPE_LIST) {
                                Class c1 = R.array.class;
                                int array = c1.getField(parser.getAttributeValue(null, ATTR_ARRAY)).getInt(null);
                                item.put(ITEMFIELD_ARRAY, array);
                            }

                            // default value.
                            String defaultValue = parser.getAttributeValue(null, ATTR_DEFAULTVALUE);
                            if (!TextUtils.isEmpty(defaultValue)) {
                                switch (type) {
                                    case DATATYPE_BOOLEAN:
                                        item.put(ITEMFIELD_DEFAULT, Boolean.parseBoolean(defaultValue));
                                        break;

                                    case DATATYPE_INTEGER:
                                    case DATATYPE_LIST:
                                        item.put(ITEMFIELD_DEFAULT, Integer.parseInt(defaultValue));
                                        break;

                                    case DATATYPE_STRING:
                                        item.put(ITEMFIELD_DEFAULT, defaultValue);
                                        break;

                                    case DATATYPE_FLOAT:
                                        item.put(ITEMFIELD_DEFAULT, Float.parseFloat(defaultValue));
                                        break;
                                }
                            }
                            curList.add(item);
                        }
                        break;

                    case XmlPullParser.END_TAG:
                        tag = parser.getName();
                        if (TAG_GROUP.equals(tag)) {
                            m_inflatedData.put(groupKey, curList);
                            loadDefaultValues(curList);
                        }
                        break;
                }
                eventType = parser.next();
            }
            input.close();
        } catch (Exception e) {
            Log.e("PreferencesHelper", "Preferences inflate failed", e);
        }
    }

    public ArrayList<HashMap<String, Object>> getInflatedData(String name) {
        if (m_inflatedData != null) {
            return m_inflatedData.get(name);
        }
        return null;
    }

    private void loadDefaultValues(ArrayList<HashMap<String, Object>> data) {
        // default values.
        if (m_defaultValues == null) {
            m_defaultValues = new HashMap<String, Object>();
        }
        int len = data.size();
        for (int i = 0; i < len; i++) {
            HashMap<String, Object> item = data.get(i);
            String key = (String) item.get(ITEMFIELD_KEY);
            Object defaultValue = item.get(ITEMFIELD_DEFAULT);
            if (defaultValue != null) {
                m_defaultValues.put(key, defaultValue);
            }
        }
    }

    public void registerActivity(Activity activity, ArrayList<HashMap<String, Object>> binding, boolean applyNow) {
        m_registeredActivities.put(activity, binding);
        loadDefaultValues(binding);
        if (applyNow) {
            apply2Activity(activity);
        }
    }

    public void unregisterActivity(Activity activity) {
        if (m_registeredActivities != null && m_registeredActivities.containsKey(activity)) {
            m_registeredActivities.remove(activity);
        }
    }

    public void apply2Activity(Activity activity) {
        if (m_registeredActivities.containsKey(activity)) {
            ArrayList<HashMap<String, Object>> bindingData = m_registeredActivities.get(activity);
            int len = bindingData.size();
            for (int i = 0; i < len; i++) {
                bindView(activity, bindingData.get(i));
            }
        }
    }

    /**
     * @param @return
     * @return SharedPreferences
     * @throws
     * @Title: initPreferences
     * @Description: 初始化用户设置
     */
    private SharedPreferences getPreferences() {
        if (m_preferences != null) {
            return m_preferences;
        }
        return PreferenceManager.getDefaultSharedPreferences(m_context);
    }

    private void bindView(final Activity activity, final HashMap<String, Object> data) {
        final String key = (String) data.get(ITEMFIELD_KEY);
        int viewId = Utils.convertToInt(data.get(ITEMFIELD_VIEW), 0);
        View v = activity.findViewById(viewId);
        final int type = Utils.convertToInt(data.get(ITEMFIELD_TYPE), 0);
        Object defaultValue = data.get(ITEMFIELD_DEFAULT);

        if (v instanceof CheckBox) {
            boolean b = getPreferences().getBoolean(key, defaultValue == null ? false : (Boolean) defaultValue);
            CheckBox ckb = (CheckBox) v;
            ckb.setChecked(b);
            ckb.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
                public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                    Object tag = buttonView.getTag();
                    if (tag instanceof CompoundButton.OnCheckedChangeListener) {
                        ((CompoundButton.OnCheckedChangeListener) tag).onCheckedChanged(buttonView, isChecked);
                    }
                    SharedPreferences.Editor editor = m_preferences.edit();
                    editor.putBoolean(key, isChecked);
                    editor.commit();
                }
            });
        } else if (v instanceof TextView) {
            String s = null;
            switch (type) {
                case DATATYPE_INTEGER:
                    s = "" + getPreferences().getInt(key, defaultValue == null ? 0 : Utils.convertToInt(defaultValue, 0));
                    break;

                case DATATYPE_STRING:
                    s = getPreferences().getString(key, defaultValue == null ? null : (String) defaultValue);
                    break;

                case DATATYPE_FLOAT:
                    s = "" + getPreferences().getFloat(key, defaultValue == null ? 0 : (Float) defaultValue);
                    break;

                case DATATYPE_LIST:
                    String[] list = activity.getResources().getStringArray(Utils.convertToInt(data.get(ITEMFIELD_ARRAY), 0));
                    s = list[getPreferences().getInt(key, defaultValue == null ? 0 : Utils.convertToInt(defaultValue, 0))];
                    break;
            }

            final TextView tv = (TextView) v;

            tv.setText(s);
            PreferenceTextView ptv = (PreferenceTextView) tv;
            ptv.setValueText(s);
            // ptv.setValueText(s);
            ptv.setOnPreferenceChangedListener(new PreferenceTextView.OnPreferenceChangedListener() {
                public void onPreferenceChanged(PreferenceTextView view, CharSequence oldText, CharSequence newText) {
                    String text = (String) view.getValueText();
                    SharedPreferences.Editor editor = getPreferences().edit();
                    if (TextUtils.isEmpty(text)) {
                        editor.remove(key);
                    } else {
                        switch (type) {
                            case DATATYPE_INTEGER:
                                editor.putInt(key, Integer.parseInt(text));
                                break;

                            case DATATYPE_STRING:
                                editor.putString(key, text);
                                break;

                            case DATATYPE_FLOAT:
                                editor.putFloat(key, Float.parseFloat(text));
                                break;

                            case DATATYPE_LIST:
                                String[] list = activity.getResources().getStringArray(Utils.convertToInt(data.get(ITEMFIELD_ARRAY), 0));
                                int index = 0;
                                for (int i = 0; i < list.length; i++) {
                                    if (text.equals(list[i])) {
                                        index = i;
                                        break;
                                    }
                                }
                                editor.putInt(key, index);
                                break;
                        }
                    }
                    editor.commit();
                }
            });
        }
    }

    public String getString(String key) {
        if (m_defaultValues == null) {
            m_defaultValues = new HashMap<String, Object>();
        }
        return getPreferences().getString(key, (String) m_defaultValues.get(key));
    }

    public void saveString(String key, String value) {
        SharedPreferences.Editor editor = getPreferences().edit();
        editor.putString(key, value);
        editor.commit();
    }

    public int getInt(String key) {
        if (m_defaultValues == null) {
            m_defaultValues = new HashMap<String, Object>();
        }
        return getPreferences().getInt(key, Utils.convertToInt(m_defaultValues.get(key), 0));
    }

    public int getInt(String key, int defaultValue) {
        return getPreferences().getInt(key, defaultValue);
    }

    public void saveInt(String key, int value) {
        SharedPreferences.Editor editor = getPreferences().edit();
        editor.putInt(key, value);
        editor.commit();
    }

    public boolean getBoolean(String key) {
        if (m_defaultValues == null) {
            m_defaultValues = new HashMap<String, Object>();
        }
        return getPreferences().getBoolean(key, (Boolean) m_defaultValues.get(key));
    }

    public boolean getBoolean(String key, boolean defaultValue) {
        return getPreferences().getBoolean(key, defaultValue);
    }

    public void saveBoolean(String key, boolean value) {
        SharedPreferences.Editor editor = getPreferences().edit();
        editor.putBoolean(key, value);
        editor.commit();
    }

    public float getFloat(String key) {
        if (m_defaultValues == null) {
            m_defaultValues = new HashMap<String, Object>();
        }
        return getPreferences().getFloat(key, (Float) m_defaultValues.get(key));
    }

    public float getFloat(String key, float defaultValue) {
        return getPreferences().getFloat(key, defaultValue);
    }

    public void saveFloat(String key, float value) {
        SharedPreferences.Editor editor = getPreferences().edit();
        editor.putFloat(key, value);
        editor.commit();
    }

    public void clear() {
        SharedPreferences.Editor editor = getPreferences().edit();
        editor.clear();
        editor.apply();
    }
}
